#include "ZipBuilder.h"
#include "FileUtils.h"
#include "CrcCalculator.h"
#include "Util.h"

ZipBuilder::ZipBuilder() { }

ZipBuilder::~ZipBuilder() { }

FileHeader* ZipBuilder::buildFileHeaderStructure(FilePathData filePathData)
{
    FileHeader* fileHeader = new FileHeader();
    FILE* file = fopen(filePathData.fullPath_.c_str(), "rb");
    if(file)
    {
        struct tm* lastModificationTime = getLastModificationTimeAndDate(filePathData.fullPath_.c_str());

        if(isFile(filePathData.fullPath_.c_str()))
        {
            fileHeader->fileData_ = getFileContent(file); //0
            fileHeader->unCompressedSize_ = getFileContentSize(file);
            fileHeader->compressedSize_ = fileHeader->unCompressedSize_; //0
        }

        fileHeader->fileNameLength_ = filePathData.relativePath_.size(); //0
        fileHeader->fileName_ = (char*) malloc(fileHeader->fileNameLength_);
        memcpy(fileHeader->fileName_, filePathData.relativePath_.c_str(), fileHeader->fileNameLength_);
        fileHeader->versionNedded_ = 0;
        fileHeader->flag_ = 0;
        fileHeader->compressionMethod_ = 0;
        fileHeader->lastModifiedTime_ = fileHeader->parseTimeToShort(lastModificationTime);
        fileHeader->lastModifiedDate_ = fileHeader->parseDateToShort(lastModificationTime);
        fileHeader->crc_ = fileHeader->calculateCRC();
        fileHeader->extraFieldLength_ = 28;
        fileHeader->extraField_ = (char*) malloc(strlen("UT\t"));
        strcpy(fileHeader->extraField_, "UT\t");
        fileHeader->versionNedded_ = 10;
    }
    return fileHeader;
}

void ZipBuilder::buildEndOfCentralDirectory()
{
    this->endOfCentralDirectory_ = new EndOfCentralDirectory();
    this->endOfCentralDirectory_->centralDirStartOnDisk_ = 0;
    this->endOfCentralDirectory_->commentLength_ = 0;
    this->endOfCentralDirectory_->comment_ = 0;
    this->endOfCentralDirectory_->numOfThisDisk_ = 0;
    this->endOfCentralDirectory_->numOfcentralDirRecordsOnThisDisk_ = 1;
    this->endOfCentralDirectory_->offsetOfStartOfCentralDir_ = 0;
    this->endOfCentralDirectory_->sizeOfCentralDir_ = 0;
    this->endOfCentralDirectory_->totalNumOfcentralDirRecords_ = 1;
}

std::vector<FileHeader*> ZipBuilder::assembleCompressedZipFile(std::vector<FilePathData> pathsList)
{
    buildEndOfCentralDirectory();

    for(std::vector<FilePathData>::iterator pathIt = pathsList.begin();
            pathIt != pathsList.end(); pathIt++)
    {
        FileHeader* header = buildFileHeaderStructure((*pathIt));
        CentralDirectory* centralDirectory = new CentralDirectory(header);
        header->setCentralDirectory(centralDirectory);
        this->fileHeadersList_.push_back(header);
        this->endOfCentralDirectory_->sizeOfCentralDir_ += centralDirectory->size();
    }

    this->endOfCentralDirectory_->totalNumOfcentralDirRecords_ = this->fileHeadersList_.size();

    return this->fileHeadersList_;
}
